package com.huawang.mdesign.model.service.inter;


import com.huawang.business.service.model.core.InternalUmlService;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.mdesign.model.service.config.UAFModelManagerConfig;
import com.huawang.mdesign.model.service.config.specification.Element;
import com.huawang.mdesign.model.service.config.specification.InstanceSpecification;
import com.huawang.mdesign.model.service.config.specification.Property;
import com.huawang.mdesign.model.service.config.specification.Slot;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.util.List;


/**
 * 模型的约束服务类
 */
@Service
@Primary
public class ModelConstraintService {
    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private UAFModelManagerConfig managerConfig;

    /**
     * 根据源和目标两端的类型，自动应用合适的Role构造型
     *
     * @param projectId
     * @param source
     * @param target
     * @return
     */
    @Nullable
    public String getAppliedStereotypeForProperty(String projectId, MetaClassInstance source, MetaClassInstance target) {
        if (source != null && target != null) {
            List<Element> propertyConstraints = this.managerConfig.getElementConstraintConfig().get(UMLDefinitionConstants.Property);
            if (propertyConstraints != null) {
                for (Element propertyConstraint : propertyConstraints) {
                    if (propertyConstraint instanceof Property &&
                            ((Property) propertyConstraint).getClazz() != null && ((Property) propertyConstraint).getType() != null &&
                            this.internalUmlService.checkInstanceType(projectId, source, ((Property) propertyConstraint).getClazz()) &&
                            this.internalUmlService.checkInstanceType(projectId, target, ((Property) propertyConstraint).getType())) {
                        return propertyConstraint.getKey();
                    }
                }
            }
        }
        return null;
    }


    /**
     * 根据类型获得对应的Slot约束
     *
     * @param type
     * @return
     */
    @Nullable
    public Slot getSlotConstraintByType(String type) {
        List<Element> slotConstraints = this.managerConfig.getElementConstraintConfig().get(UMLDefinitionConstants.Slot);
        if (slotConstraints != null) {
            for (Element slotConstraint : slotConstraints) {
                if (slotConstraint.getKey().equals(type)) {
                    return (Slot) slotConstraint;
                }
            }
        }
        return null;
    }

    /**
     * 根据实例模型获得对应的Classifier
     *
     * @param projectId
     * @param instance
     * @return
     */
    @NotNull
    public String getInstanceSpecificationClassifierByInstance(String projectId, MetaClassInstance instance) {
        List<MetaClassInstance> appliedStereotypes = internalUmlService.queryListInstanceProperty(projectId, instance, UMLDefinitionConstants.Element_appliedStereotype);
        if (!appliedStereotypes.isEmpty()) {
            return getInstanceSpecificationClassifier(projectId, appliedStereotypes.get(0));
        }
        return UMLDefinitionConstants.Classifier;
    }

    /**
     * 根据构造型的父类递归查找Classifier属性
     *
     * @param projectId
     * @param stereotype
     * @return
     */
    @NotNull
    private String getInstanceSpecificationClassifier(String projectId, MetaClassInstance stereotype) {
        List<Element> instanceSpecificationConstraints = this.managerConfig.getElementConstraintConfig().get(UMLDefinitionConstants.InstanceSpecification);
        if (instanceSpecificationConstraints != null) {
            //1. 如果找到对应的配置，则获得其classifier
            for (Element instanceSpecificationConstraint : instanceSpecificationConstraints) {
                if (instanceSpecificationConstraint.getKey().equals(stereotype.getUUID())) {
                    String classifier = ((InstanceSpecification) instanceSpecificationConstraint).getClassifier();
                    if(StringUtils.isNotBlank(classifier)) {
                        return classifier;
                    }
                }
            }
            //2. 从父类中递归获取
            List<MetaClassInstance> generals = internalUmlService.queryListInstanceProperty(projectId, stereotype, UMLDefinitionConstants.Classifier_general);
            for (MetaClassInstance general : generals) {
                String classifier = getInstanceSpecificationClassifier(projectId, general);
                if(!UMLDefinitionConstants.Classifier.equals(classifier)) {
                    return classifier;
                }
            }
        }
        return UMLDefinitionConstants.Classifier;
    }
}
